use crate::{ApiError, ApiResult, ToError};
use data_encoding::HEXLOWER;
use ring::aead;
use ring::aead::UnboundKey;

const KEY: [u8; 16] = *b"aes-128-gcm-rust";
const NONCE: [u8; 12] = *b"aes-nonce-rs";

/// AES_128_GCM加密
pub fn encode<D: AsRef<[u8]>>(data: D) -> ApiResult<String> {
    let key =
        UnboundKey::new(&aead::AES_128_GCM, &KEY).to_err(|| ApiError::Biz("aes加密错误".into()))?;
    let key = aead::LessSafeKey::new(key);
    let nonce = aead::Nonce::assume_unique_for_key(NONCE);
    // 4. 加密
    let mut ciphertext = Vec::from(data.as_ref());
    let aad = aead::Aad::from(b""); // 可选附加数据
    key.seal_in_place_append_tag(nonce, aad, &mut ciphertext)
        .to_err(|| ApiError::Biz("aes加密错误".into()))?;
    Ok(HEXLOWER.encode(ciphertext.as_ref()))
}

/// AES_128_GCM解密
pub fn decode<S: AsRef<[u8]>>(data: S) -> ApiResult<String> {
    let key =
        UnboundKey::new(&aead::AES_128_GCM, &KEY).to_err(|| ApiError::Biz("aes解密错误".into()))?;
    let key = aead::LessSafeKey::new(key);
    let nonce = aead::Nonce::assume_unique_for_key(NONCE);
    let aad = aead::Aad::from(b""); // 可选附加数据
    let mut vec = HEXLOWER
        .decode(data.as_ref())
        .to_err(|| ApiError::Biz("aes解密错误".into()))?;
    let mopening = key
        .open_in_place(nonce, aad, &mut vec)
        .to_err(|| ApiError::Biz("aes解密错误".into()))?;
    String::from_utf8(mopening.to_vec()).to_err(|| ApiError::Biz("aes解密错误".into()))
}

/// AES_128_GCM解密
pub fn decode_vec<S: AsRef<[u8]>>(data: S) -> ApiResult<Vec<u8>> {
    let key =
        UnboundKey::new(&aead::AES_128_GCM, &KEY).to_err(|| ApiError::Biz("aes解密错误".into()))?;
    let key = aead::LessSafeKey::new(key);
    let nonce = aead::Nonce::assume_unique_for_key(NONCE);
    let aad = aead::Aad::from(b""); // 可选附加数据
    let mut vec = HEXLOWER
        .decode(data.as_ref())
        .to_err(|| ApiError::Biz("aes解密错误".into()))?;
    let mopening = key
        .open_in_place(nonce, aad, &mut vec)
        .to_err(|| ApiError::Biz("aes解密错误".into()))?;
    Ok(mopening.to_vec())
}

// /// AES_256_GCM加密
// pub fn encode_aes_256_gcm<D: AsRef<[u8]>>(data: D) -> String {
//     let key = UnboundKey::new(&aead::AES_256_GCM, &KEY).expect("key长度错误");
//     let key = aead::LessSafeKey::new(key);
//     let nonce = aead::Nonce::assume_unique_for_key(NONCE);
//     // 4. 加密
//     let mut ciphertext = Vec::from(data.as_ref());
//     let aad = aead::Aad::from(b""); // 可选附加数据
//     key.seal_in_place_append_tag(nonce, aad, &mut ciphertext).expect("加密失败");
//     HEXLOWER.encode(ciphertext.as_ref())
// }
//
// /// AES_256_GCM解密
// pub fn decode_aes_256_gcm<S: AsRef<[u8]>>(data: S) -> String {
//     let key = UnboundKey::new(&aead::AES_256_GCM, &KEY).expect("key长度错误");
//     let key = aead::LessSafeKey::new(key);
//     let nonce = aead::Nonce::assume_unique_for_key(NONCE);
//     let aad = aead::Aad::from(b""); // 可选附加数据
//     let mut vec = HEXLOWER.decode(data.as_ref()).expect("解密错误");
//     let opening_result = key.open_in_place(nonce, aad, &mut vec);
//     let mopening = opening_result.expect("解密错误");
//     String::from_utf8(mopening.to_vec()).expect("解密错误")
// }
